package com.world.common.util;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by xinyu.qiu on 2015/7/10.
 */
public class CodeTemplateUtil {
    /**
     * 构造一个对象
     *
     * @param toClazz
     * @param toClazzName
     * @param fromClass
     * @param fromClazzName
     */
    public static void printSetInfo(Class toClazz, String toClazzName, Class fromClass, String fromClazzName) {
        Method[] toMethods = toClazz.getMethods();

        Set<String> toSetNames = new HashSet<>();
        for (Method method : toMethods) {
            String className = method.getName();
            if (className.startsWith("set")) {
                toSetNames.add(className.substring(3));
            }
        }
        Set<String> fromGetNames = new HashSet<>();
        Method[] fromMethods = fromClass.getMethods();
        for (Method method : fromMethods) {
            String className = method.getName();
            if (className.startsWith("get")) {
                fromGetNames.add(className.substring(3));
            }
        }
        System.out.println(toClazz.getSimpleName() + " " + toClazzName + " = new " + toClazz.getSimpleName() + "();");
        for (String setMethodStr : toSetNames) {
            if (fromGetNames.contains(setMethodStr)) {
                System.out.println(toClazzName + ".set" + setMethodStr + "(" + fromClazzName + ".get" + setMethodStr + "());");
            } else {
                System.out.println(toClazzName + ".set" + setMethodStr + "(null);");
            }
        }
    }


    /**
     * printResource(xxController.Class) 导出这个controller的权限。
     *
     * @param controllerClass
     */
    public static void printResource(Class controllerClass) {
        RequestMapping baseRequestMapping = (RequestMapping) controllerClass.getAnnotation(RequestMapping.class);
        String baseURI_prefix = null;
        if (baseRequestMapping != null && ArrayUtils.isNotEmpty(baseRequestMapping.value())) {
            baseURI_prefix = baseRequestMapping.value()[0];
        }
        if (baseURI_prefix == null) {
            baseURI_prefix = "";
        }
        Method[] methods = controllerClass.getMethods();
        List<List<String>> result = new ArrayList<>();
        if (ArrayUtils.isNotEmpty(methods)) {
            for (Method method : methods) {
                RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
                ResponseBody responseBody = method.getAnnotation(ResponseBody.class);
                String fullClassName = controllerClass.getName();
                String domainName = fullClassName.split("\\.")[2];
                List<String> resources = new ArrayList<>();


                if (requestMapping != null) {
                    //资源名称	              资源类型	    key	                                                资源URI	                      所属域	    所属模块	             一级菜单	二级菜单	关联菜单key
                    String methodURI = baseURI_prefix + (ArrayUtils.isNotEmpty(requestMapping.value()) ? requestMapping.value()[0] : "");
                    String key = domainName + "_request_" + (methodURI.startsWith("/") ? methodURI.replaceFirst("/", "").replace("/", "_") : methodURI.replace("/", "_"));
                    resources.add("资源名称内容");
                    resources.add("请求");
                    resources.add(key);
                    resources.add(methodURI);
                    resources.add("所属模块");
                    if (responseBody == null) {
                        resources.add("一级菜单");
                        resources.add("二级菜单");
                        resources.add("关联菜单key");
                    } else {
                        resources.add("");
                        resources.add("");
                        resources.add("");
                    }
                    result.add(resources);
                }
            }
        }

        for (List<String> resources : result) {
            for (String str : resources) {
                System.out.print(str);
                System.out.print("\t");
            }
            System.out.println("");
        }
    }

    /**
     * excel2003，按照如下格式填写，生成entity字段，set get方法，jpa配置文件
     * 类型	字段key	描述	数据库字段类型	default
     * String	customerCode	卖家编码,保证唯一,必填	varchar(100)	1
     * @param filePath
     * @param clazz
     */
    public static void generateEntityFromXLS(String filePath, Class clazz) {
        try {
            InputStream is = null;
            is = new FileInputStream(filePath);
            List<String[]> itemList = ExcelUtil.importExcel(new BufferedInputStream(is), 1, -1);
            Set<String> baseType = new HashSet<>();
            baseType.add(String.class.getSimpleName());
            baseType.add(Long.class.getSimpleName());
            baseType.add(Double.class.getSimpleName());
            baseType.add(Integer.class.getSimpleName());
            baseType.add(Boolean.class.getSimpleName());
            baseType.add(Byte.class.getSimpleName());
            baseType.add(Float.class.getSimpleName());
            baseType.add(Character.class.getSimpleName());
            for (String[] filed : itemList) {
                if (StringUtils.isNotEmpty(filed[2])) {
                    System.out.println("/**");
                    System.out.println("*" + filed[2]);
                    System.out.println("*/");
                }
                System.out.println("private " + filed[0] + " " + filed[1] + ";");
            }

            System.out.println();
            System.out.println("//************* set get 构造方法 ******************");
            for (String[] filed : itemList) {
                if(filed.length>3 && StringUtils.isNotEmpty(filed[3])){
                    System.out.println("@Column(name = \"" + camelToUnderline(filed[1]) + "\")");
                    if (!baseType.contains(filed[0])) {
                        System.out.println("@Enumerated(EnumType.STRING)");
                    }
                }
                System.out.println("public " + filed[0] + " get" + (filed[1].substring(0, 1).toUpperCase() + filed[1].substring(1)) + "() {");
                System.out.println("    return " + filed[1] + " ;");
                System.out.println("}");
                System.out.println();
                System.out.println("public void set" + (filed[1].substring(0, 1).toUpperCase() + filed[1].substring(1)) + "(" + filed[0] + " " + filed[1] + ") {");
                System.out.println("    this." + filed[1] + " = " + filed[1] + " ;");
                System.out.println("}");
                System.out.println();
            }
            System.out.println("//************* JPA-XML ******************");
            String userName = System.getenv().get("USERNAME");
            String tableName = camelToUnderline(clazz == null ? "table_name" : clazz.getSimpleName());
            System.out.println("<changeSet author=\"" + userName + "\" id=\"" + tableName + "_" + userName + "_1\">");
            System.out.println("<createTable tableName=\"" + tableName + "\">");
            System.out.println("<column name=\"id\" type=\"bigint\" autoIncrement=\"true\" startWith=\"1\">");
            System.out.println("<constraints nullable=\"false\" primaryKey=\"true\" primaryKeyName=\"pk_" + tableName + "\"/>");
            System.out.println("</column>");
            for (String[] filed : itemList) {
                if(filed.length>3 && StringUtils.isEmpty(filed[3])){
                    continue;
                }
                StringBuilder sb = new StringBuilder();
                sb.append("<column name=\"").append(camelToUnderline(filed[1])).append("\" type=\"").append(filed[3]).append("\"");
                if (filed.length > 2 && StringUtils.isNotEmpty(filed[2])) {
                    sb.append(" remarks=\"").append(filed[2]).append("\"");
                }
                if (filed.length > 4 && StringUtils.isNotEmpty(filed[4])) {
                    sb.append(" defaultValue=\"").append(filed[4]).append("\"");
                }
                sb.append("/>");
                System.out.println(sb.toString());
            }
            System.out.println(" <column name=\"creater\" type=\"varchar(50)\">\n" +
                    " <constraints nullable=\"false\"/>\n" +
                    " </column>\n" +
                    " <column name=\"create_time\" type=\"bigint\">\n" +
                    " <constraints nullable=\"false\"/>\n" +
                    " </column>\n" +
                    " <column name=\"modifier\" type=\"varchar(50)\">\n" +
                    " <constraints nullable=\"false\"/>\n" +
                    " </column>\n" +
                    " <column name=\"modify_time\" type=\"bigint\">\n" +
                    " <constraints nullable=\"false\"/>\n" +
                    " </column>\n" +
                    " <column name=\"version\" type=\"bigint\">\n" +
                    " <constraints nullable=\"false\"/>\n" +
                    " </column>\n" +
                    " </createTable>\n" +
                    "</changeSet>");
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static final char UNDERLINE = '_';

    //驼峰命名转下划线命名 camelName -> camel_name
    public static String camelToUnderline(String param) {
        if (param == null || "".equals(param.trim())) {
            return "";
        }
        int len = param.length();
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c = param.charAt(i);
            if (Character.isUpperCase(c)) {
                if(sb.length()>0){
                    sb.append(UNDERLINE);
                }

                sb.append(Character.toLowerCase(c));
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    //下划线命名转驼峰命名 camel_name -> camelName
    public static String underlineToCamel(String param) {
        if (param == null || "".equals(param.trim())) {
            return "";
        }
        int len = param.length();
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c = param.charAt(i);
            if (c == UNDERLINE) {
                if (++i < len) {
                    sb.append(Character.toUpperCase(param.charAt(i)));
                }
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    //下划线命名转驼峰命名 camel_name -> camelName
    public static String underlineToCamel2(String param) {
        if (param == null || "".equals(param.trim())) {
            return "";
        }
        StringBuilder sb = new StringBuilder(param);
        Matcher mc = Pattern.compile("_").matcher(param);
        int i = 0;
        while (mc.find()) {
            int position = mc.end() - (i++);
            sb.replace(position - 1, position + 1, sb.substring(position, position + 1).toUpperCase());
        }
        return sb.toString();
    }

    /**
     * 生成导出excel方法的static方法
     * @param filePath
     */
    public static void generateExportStatic(String filePath){
        try {
            InputStream is = null;
            is = new FileInputStream(filePath);
            List<String[]> itemList = ExcelUtil.importExcel(new BufferedInputStream(is), 1, -1);
            System.out.println();
            System.out.println("//************* static{}方法 ******************");
            System.out.println("DEFAULT_FIELDS = new ArrayList<>();");
            for (String[] filed : itemList) {
                System.out.println("DEFAULT_FIELDS.add(\""+filed[1]+"\");");
            }
            System.out.println();
            System.out.println("DEFAULT_FIELD_HEADER_MAP = new HashMap<>();");
            for (String[] filed : itemList) {
                System.out.println("DEFAULT_FIELD_HEADER_MAP.put(\""+filed[1]+"\",\""+filed[2]+"\");");
            }
            System.out.println();
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[]args){
        generateEntityFromXLS("C:\\Users\\xinyu.qiu\\Desktop\\自动化代码\\Entity.xls",null);
    }

}
